/* 
  Copyright (c) SilverLining 2015
  Date:    2016-1-7
  File:    m.h  
  Description: 
    M native library static header file. Contains most of the native code for the M project.
*/

#ifndef _M_H_
#define _M_H_

#define ATOMIC_ALIGNMENT MEMORY_ALLOCATION_ALIGNMENT
#define ATOMIC_ALIGN __declspec(align(ATOMIC_ALIGNMENT))

// Maximum recommended representable size for an object.
#define TOSTRING_BUFSZ 4096

typedef unsigned char byte;

/// <summary>
/// This namespace is the base namespace for the M project.
/// </summary>
namespace m
{
	/// <summary>
	/// Utilities for allocating and deallocating aligned pool memory.
	/// </summary>
	namespace alloc
	{
		class _pool_bucket;

		/// <summary>
		/// Structure for aligned memory allocation.
		/// </summary>
		struct _aligned
		{
		};
		/// <summary>
		/// Tag for aligned memory allocation.
		/// </summary>
		extern _aligned aligned;

		/// <summary>
		/// Represent a pool heap node.
		/// </summary>
		class _pool_node
		{
		public:
			_pool_node();
			~_pool_node();

			ATOMIC_ALIGN SLIST_ENTRY ItemEntry;
			_pool_bucket* _Pool;
#pragma warning(push)
#pragma warning(disable : 4200)
			ATOMIC_ALIGN unsigned char Data[0];
#pragma warning(pop)
		private:
			// Make this class non-copyable.
			_pool_node(const _pool_node&);
			_pool_node& operator=(const _pool_node&);
		};

		class _pool;

		/// <summary>
		/// Represent a fixed-sized pool memory bucket.
		/// </summary>
		class _pool_bucket
		{
		public:
			/// <summary>
			/// Constructor.
			/// </summary>
			/// <param name="MaxSize">The maximum size of the pool bucket.</param>
			_pool_bucket(const size_t& MaxSize);
			~_pool_bucket();

			/// <summary>
			/// Get or allocate a node, returning it immediately.
			/// </summary>
			/// <param name="pool">The pool to get the memory in.</param>
			/// <returns>The address of the heap space that was allocated.</returns>
			void* get(_pool* pool);

			/// <summary>
			/// Put an object back on the pool.
			/// </summary>
			/// <param name="pool">The pool to place the memory in.</param>
			/// <param name="data">The heap to place.</param>
			static void put(_pool* pool, void* data);

			/// <summary>
			/// Clear up space from the pool.
			/// </summary>
			/// <param name="pool">The pool to clear memory from.</param>
			/// <param name="ClearSpace">The amount of clear space, in bytes.</param>
			/// <returns>The size of cleared memory space, in bytes.</returns>
			size_t clear(_pool* pool, const size_t& ClearSpace);

			// Aligned new/delete
			static void* operator new(size_t sz);
			static void operator delete(void* ptr);

			size_t MaxSize;
		private:
			// Make this class non-copyable.
			_pool_bucket(const _pool_node&);
			_pool_bucket& operator=(const _pool_node&);

			ATOMIC_ALIGN SLIST_HEADER _ListHead;
		};

		///<summary> Represent a generic object pool which can be used to recycle memory space on demand.</summary>
		class _pool
		{
		public:
			_pool();
			~_pool();

			/// <summary>
			/// Get or allocate a node, returning it immediately.
			/// </summary>
			/// <param name="count">The size of the memory to be returned, in bytes.</param>
			/// <returns>The address of the heap space that was allocated.</returns>
			void* get(const size_t& count);
			
			/// <summary>
			/// Put an object back on the pool.
			/// </summary>
			/// <param name="data">The heap to place.</param>
			void put(void* data);

			/// <summary>
			/// Clear up space from the pool.
			/// </summary>
			/// <param name="ClearSpace">The amount of clear space, in bytes.</param>
			/// <returns>The size of cleared memory space, in bytes.</returns>
			size_t clear(const size_t& ClearSpace);

			volatile ATOMIC_ALIGN size_t UnusedPoolSize;
			volatile ATOMIC_ALIGN size_t UsedPoolSize;
		private:
			// Make this class non-copyable.
			_pool(const _pool&);
			_pool& operator=(const _pool&);

			ATOMIC_ALIGN _pool_bucket** _Buckets;
			size_t _CountBuckets;
		};

		/// <summary>
		/// The default pool tag.
		/// </summary>
		extern _pool pool;
	} // namespace alloc
} // namespace m

#define CRIT_WAIT 4000

#pragma warning(push)
#pragma warning(disable : 4290)

/// <summary>
/// Aligned new, uses _aligned_malloc with ATOMIC_ALIGN alignment.
/// </summary>
void* operator new  (std::size_t count, m::alloc::_aligned& aligned);
/// <summary>
/// Aligned new, uses _aligned_malloc with ATOMIC_ALIGN alignment.
/// </summary>
void* operator new[](std::size_t count, m::alloc::_aligned& aligned);
/// <summary>
/// Aligned delete, uses _aligned_malloc with ATOMIC_ALIGN alignment.
/// </summary>
void operator delete(void* data, m::alloc::_aligned& aligned);
/// <summary>
/// Aligned delete, uses _aligned_malloc with ATOMIC_ALIGN alignment.
/// </summary>
void operator delete[](void* data, m::alloc::_aligned& aligned);

/// <summary>
/// Pool new, allocates from the specified pool tag.
/// </summary>
void* operator new  (std::size_t count, m::alloc::_pool& pool);
/// <summary>
/// Pool new, allocates from the specified pool tag.
/// </summary>
void* operator new[](std::size_t count, m::alloc::_pool& pool);
/// <summary>
/// Pool delete, allocates from the specified pool tag.
/// </summary>
void operator delete(void* data, m::alloc::_pool& pool);
/// <summary>
/// Pool delete, allocates from the specified pool tag.
/// </summary>
void operator delete[](void* data, m::alloc::_pool& pool);

namespace m
{
	namespace error
	{
		typedef int result;

		/// <summary>
		/// The last error result for this thread.
		/// </summary>
		extern __declspec(thread) result LastHr;

		/// <summary>
		/// Native interface for ETW routines.
		/// </summary>
		class debug_provider
		{
		public:
			debug_provider();
			~debug_provider();

			/// <summary>
			/// Log formatted text to the ETW session.
			/// </summary>
			/// <param name="hr">The error code of the trace.</param>
			/// <param name="Fmt">The format string.</param>
			void log(result hr, const wchar_t* Fmt, ...);

			/// <summary>
			/// Log an allocation to the ETW session.
			/// </summary>
			/// <param name="ptr">The heap pointer.</param>
			/// <param name="sz">The heap size.</param>
			void alloc(void* ptr, size_t sz);

			/// <summary>
			/// Log a deallocation to the ETW session.
			/// </summary>
			/// <param name="ptr">The heap pointer.</param>
			void _free(void* ptr);

			/// <summary>
			/// Log a reference to the ETW session.
			/// </summary>
			/// <param name="ptr">The heap pointer.</param>
			/// <param name="refCount">The reference count.</param>
			void reference(void* ptr, const size_t& refCount);

			/// <summary>
			/// Log a weak reference to the ETW session.
			/// </summary>
			/// <param name="ptr">The heap pointer.</param>
			void referenceweak(void* ptr);

			/// <summary>
			/// Log a release to the ETW session.
			/// </summary>
			/// <param name="ptr">The heap pointer.</param>
			/// <param name="refCount">The reference count.</param>
			void release(void* ptr, const size_t& refCount);

			/// <summary>
			/// Log a message to the ETW session.
			/// </summary>
			/// <param name="messageType">The message type.</param>
			/// <param name="sender">The message sender.</param>
			/// <param name="data">The message data.</param>
			void message(const wchar_t* messageType, void* sender, void* data);

		private:
			DWORD ThreadId();
			FILETIME SysTime();
			wchar_t* FormatV(const wchar_t* Fmt, va_list args);
		};

		/// <summary>
		/// The default debug provider.
		/// </summary>
		extern debug_provider dbg;
	} // namespace error

	/// <summary>
	/// Monochrome exception type. This is used instead of return codes to indicate an operation failed by encapsulating the error code as an exception.
	/// </summary>
	class bad_result_exception : public std::exception
	{
	public:
		typedef std::exception BaseType;

		/// <summary>
		/// The encapsulated error code.
		/// </summary>
		error::result ErrorCode;

		bad_result_exception();
		bad_result_exception(bad_result_exception& other);
		bad_result_exception(const error::result& errorCode);
		bad_result_exception(const error::result& errorCode, const char* const& message);

		bad_result_exception& operator=(const bad_result_exception& other);
	};

} // namespace m

#include "m_error.h"

//
// More debug goodness. Macros which can be used to encapsulate various
// events with an error code.
//

#ifndef _DISABLE_MONO_DEBUGGING

/// <summary>
/// Log debug info
/// </summary>
#define DBGL(...) m::error::dbg.log(m::error::LastHr, __VA_ARGS__)
/// <summary>
/// Log debug spew + set the last HResult
/// </summary>
#define DBGH(X,...) { \
	m::error::LastHr = (long)(X); \
	m::error::dbg.log(m::error::LastHr, __VA_ARGS__); \
}
/// <summary>
/// Log debug spew + set the last Win32 error
/// </summary>
#define DBGW(X,...) { \
	m::error::LastHr = HRESULT_FROM_WIN32((long)(X)); \
	m::error::dbg.log(m::error::LastHr, __VA_ARGS__); \
}
/// <summary>
/// Log debug allocation
/// </summary>
#define DBGALLOC(X,Y) m::error::dbg.alloc(X,Y);
/// <summary>
/// Log debug free
/// </summary>
#define DBGFREE(X) m::error::dbg._free(X);
/// <summary>
/// Log debug reference
/// </summary>
#define DBGREFERENCE(X,Y) m::error::dbg.reference((void*)X,Y);
/// <summary>
/// Log debug weak reference.
/// </summary>
#define DBGREFERENCEWEAK(X) m::error::dbg.referenceweak((void*)X);
/// <summary>
/// Log debug release.
/// </summary>
#define DBGRELEASE(X,Y) m::error::dbg.release((void*)X,Y);
#else
#define DBGL(...)
#define DBGH(X,...)
#define DBGW(X,...)
#define DBGALLOC(X,Y)
#define DBGFREE(X) 
#define DBGREFERENCE(X,Y)
#define DBGREFERENCEWEAK(X)
#define DBGRELEASE(X,Y)
#endif // _DISABLE_MONO_DEBUGGING

#define ID_NOTARCHIVED -1

namespace m
{
	class weak_ref;
	class archiver;

	/// <summary>
	/// Represent the base object model class. This is designed to represent any native object used by our compositor, and includes an implementation of
	/// reference counting that supports strong and weak references.
	/// </summary>
	class object
	{
	public:
		friend void* ::operator new (std::size_t count, m::alloc::_pool& pool);
		friend class archiver;

		object();
		virtual ~object();

		/// <summary>
		/// Reference this object, incrementing the reference count. 
		/// </summary>
		void reference() volatile;
		/// <summary>
		/// Reference this object, incrementing the reference count. 
		/// </summary>
		/// <param name="additionalRefCount">The additional counts to reference by.</param>
		void reference(const size_t& additionalRefCount) volatile;
		/// <summary>
		/// Return a weak reference to this object. Each object holds one weak reference to itself,
		/// and if it does not exist it will be atomically created before being returned.
		/// </summary>
		/// <returns>The weak reference for this object.</returns>
		weak_ref* reference_weak() volatile;
		/// <summary>
		/// Deference this object. If the reference count has reached 0, it should be deleted.
		/// You must have a matching Release call with every call to a ctor or Reference method in your code
		/// to ensure things get cleaned up.
		/// </summary>
		void release() volatile;
		/// <summary>
		/// The object current reference count.
		/// </summary>
		ATOMIC_ALIGN volatile size_t RefCount;

		/// <summary>
		/// Provide an object description useful for debugging to the given buffer.
		/// </summary>
		/// <returns>A string buffer containing an object description.</returns>
		virtual std::wstring to_string() const;

		static void* operator new(size_t sz);
		static void operator delete(void* ptr);

	protected:
		/// <summary>
		/// Implementation of the read method for archival.
		/// </summary>
		/// <param name="archiver">The archiver to read from.</param>
		virtual void read(archiver* archiver);

		/// <summary>
		/// Implementation of the write method for archival.
		/// </summary>
		/// <param name="archiver">The archiver to write to.</param>
		virtual void write(archiver* archiver);

	private:
		object(const object&);
		object& operator=(const object&);

		alloc::_pool* _Pool;
		ATOMIC_ALIGN volatile object* _Weak;
		// Used for archival.
		ATOMIC_ALIGN volatile archiver* _Archiver;
		ptrdiff_t _Id;
	};

	/// <summary>
	/// Represent a weak reference. Internally, a weak ref chain is held by each object maintaining its reference count. When the reference count reaches 0, the weak ref chain is invalidated.
	/// </summary>
	class weak_ref : public object
	{
	public:
		friend class object;

		/// <summary>
		/// Attempt to lock this object, incrementing the object's reference count and returning it if successful.
		/// </summary>
		/// <returns>The weak reference object, if it exists.</returns>
		object* lock() volatile;

		static void* operator new(size_t sz);
		static void operator delete(void* ptr);

	private:
		weak_ref(volatile object* obj);
		weak_ref(const weak_ref&);
		weak_ref& operator=(const weak_ref&);

		ATOMIC_ALIGN volatile object* _Value;
	};

#include "m_safe.h"

	/// <summary>
	/// Represent a base class for object serializers. A serializer implements multiple methods which are used
	/// by the archiver to write or read an object to the filesystem.
	/// </summary>
	class serializer : public object
	{
	public:
		virtual ~serializer();

		/// <summary>
		/// Write the start of an object.
		/// </summary>
		/// <param name="name">The name of the object being written.</param>
		virtual void write_object_start(const wchar_t* name) = 0;
		/// <summary>
		/// Write the end of an object.
		/// </summary>
		virtual void write_object_end() = 0;
		/// <summary>
		/// Write a value.
		/// </summary>
		/// <param name="name">The name of the value being written.</param>
		/// <param name="string">The null-terminated string to write.</param>
		virtual void write_value(const wchar_t* name, const wchar_t* string) = 0;
		/// <summary>
		/// Write a value.
		/// </summary>
		/// <param name="name">The name of the value being written.</param>
		/// <param name="num">The value to write.</param>
		virtual void write_value(const wchar_t* name, double num) = 0;
		/// <summary>
		/// Write a value.
		/// </summary>
		/// <param name="name">The name of the value being written.</param>
		/// <param name="num">The value to write.</param>
		virtual void write_value(const wchar_t* name, int8_t num) = 0;
		/// <summary>
		/// Write a value.
		/// </summary>
		/// <param name="name">The name of the value being written.</param>
		/// <param name="num">The value to write.</param>
		virtual void write_value(const wchar_t* name, int16_t num) = 0;
		/// <summary>
		/// Write a value.
		/// </summary>
		/// <param name="name">The name of the value being written.</param>
		/// <param name="num">The value to write.</param>
		virtual void write_value(const wchar_t* name, int32_t num) = 0;
		/// <summary>
		/// Write a value.
		/// </summary>
		/// <param name="name">The name of the value being written.</param>
		/// <param name="num">The value to write.</param>
		virtual void write_value(const wchar_t* name, int64_t num) = 0;
		/// <summary>
		/// Write a value.
		/// </summary>
		/// <param name="name">The name of the value being written.</param>
		/// <param name="bit">The value to write.</param>
		virtual void write_value(const wchar_t* name, bool bit) = 0;
		/// <summary>
		/// Write a blob value.
		/// </summary>
		/// <param name="name">The name of the value being written.</param>
		/// <param name="data">The data to write.</param>
		/// <param name="sz">The size of the data to write, in bytes.</param>
		virtual void write_value(const wchar_t* name, const byte* data, size_t sz) = 0;

		/// <summary>
		/// Read the start of an object.
		/// </summary>
		/// <param name="name">The name of the object to read.</param>
		/// <param name="countChildren">An optional pointer which if specified indicates the number of child values in the object.</param>
		/// <returns>True if the object could be read.</returns>
		virtual bool read_object_start(const wchar_t* name, size_t* countChildren) = 0;
		/// <summary>
		/// Read the end of an object.
		/// </summary>
		virtual void read_object_end() = 0;
		/// <summary>
		/// Read a value. If the value could not be read, it should be default initialized.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="string">A pointer to a null terminated value to hold the string. If the value could not be read, it will be default initialized. If it already contains a string value, it will be reinitialized, and should be deleted by calling free after use.</param>
		virtual void read_value(const wchar_t* name, wchar_t** string) = 0;
		/// <summary>
		/// Read a value. If the value could not be read, it should be default initialized.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="num">A pointer to the number being read. If the value could not be read, it will be default initialized.</param>
		virtual void read_value(const wchar_t* name, double* num) = 0;
		/// <summary>
		/// Read a value. If the value could not be read, it should be default initialized.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="num">A pointer to the number being read. If the value could not be read, it will be default initialized.</param>
		virtual void read_value(const wchar_t* name, int8_t* num) = 0;
		/// <summary>
		/// Read a value. If the value could not be read, it should be default initialized.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="num">A pointer to the number being read. If the value could not be read, it will be default initialized.</param>
		virtual void read_value(const wchar_t* name, int16_t* num) = 0;
		/// <summary>
		/// Read a value. If the value could not be read, it should be default initialized.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="num">A pointer to the number being read. If the value could not be read, it will be default initialized.</param>
		virtual void read_value(const wchar_t* name, int32_t* num) = 0;
		/// <summary>
		/// Read a value. If the value could not be read, it should be default initialized.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="num">A pointer to the number being read. If the value could not be read, it will be default initialized.</param>
		virtual void read_value(const wchar_t* name, int64_t* num) = 0;
		/// <summary>
		/// Read a value. If the value could not be read, it should be default initialized.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="bit">A pointer to the boolean being read. If the value could not be read, it will be default initialized.</param>
		virtual void read_value(const wchar_t* name, bool* bit) = 0;
		/// <summary>
		/// Read a value. If the value could not be read, it should be default initialized.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="data">A pointer to the byte array being read. If the value could not be read, it will be default initialized. If the value has already been initialized it will be deleted, and should be deleted by calling delete[] after use.</param>
		virtual void read_value(const wchar_t* name, byte** data, size_t* sz) = 0;
	};

	/// <summary>
	/// Default initialize an object, converting the derived type to the base type.
	/// </summary>
	template <typename T>
	object* create_default_object()
	{
		return new T();
	}

	/// <summary>
	/// Represent an object archiver. The archiver persists a root object, maintaining any internal object references.
	/// </summary>
	/// <example>
	/// <para>The following example shows how to read an archive from a binary file.</para>
	/// <code>			
	/// binary_serializer* s = new binary_serializer();
	/// file_buffer* buffer = new file_buffer();
	/// archiver* a = new archiver();
	/// object* o = CreateObjectGraph();
	/// object* o2 = CreateObjectGraph();
	/// 
	/// InitGraph(o);
	/// a->archive(o, s);
	/// TestArchive(a, o);
	/// a->unarchive(o2, s);
	/// </code>
	/// </example>
	class archiver : public object
	{
	public:
		archiver();
		~archiver();

		/// <summary>
		/// Archive the root object.
		/// </summary>
		/// <param name="root">The root object to archive.</param>
		/// <param name="serializer">The serializer to use for archival.</param>
		void archive(object* root, m::serializer * serializer);
		/// <summary>
		/// Unarchive the root object.
		/// </summary>
		/// <param name="root">The root object to unarchive, which must have been constructed prior to calling this method.</param>
		/// <param name="serializer">The serializer to use for archival.</param>
		void unarchive(object* root, m::serializer * serializer);

		/// <summary>
		/// Write the start of an array.
		/// </summary>
		/// <param name="name">The name of the value to write.</param>
		void write_array_start(const wchar_t* name);
		/// <summary>
		/// Write the start of an array from inside an array.
		/// </summary>
		void write_array_start();
		/// <summary>
		/// Write an array value.
		/// </summary>
		/// <param name="obj">The object to write.</param>
		void write_array_value(object* obj);
		/// <summary>
		/// Write an array value.
		/// </summary>
		/// <param name="num">The number to write.</param>
		void write_array_value(double num);
		/// <summary>
		/// Write an array value.
		/// </summary>
		/// <param name="num">The number to write.</param>
		void write_array_value(int8_t num);
		/// <summary>
		/// Write an array value.
		/// </summary>
		/// <param name="num">The number to write.</param>
		void write_array_value(int16_t num);
		/// <summary>
		/// Write an array value.
		/// </summary>
		/// <param name="num">The number to write.</param>
		void write_array_value(int32_t num);
		/// <summary>
		/// Write an array value.
		/// </summary>
		/// <param name="num">The number to write.</param>
		void write_array_value(int64_t num);
		/// <summary>
		/// Write an array value.
		/// </summary>
		/// <param name="string">The string to write.</param>
		void write_array_value(const wchar_t* string);
		/// <summary>
		/// Write an array value.
		/// </summary>
		/// <param name="bit">The boolean to write.</param>
		void write_array_value(bool bit);
		/// <summary>
		/// Write an array value.
		/// </summary>
		/// <param name="data">The binary data to write.</param>
		/// <param name="sz">The size of the binary data, in bytes.</param>
		void write_array_value(const byte* data, size_t sz);
		/// <summary>
		/// Write the end of an array.
		/// </summary>
		void write_array_end();

		/// <summary>
		/// Write an object.
		/// </summary>
		/// <param name="name">The name of the value to write.</param>
		/// <param name="obj">The object to write.</param>
		void write_value(const wchar_t* name, object* obj);
		/// <summary>
		/// Write a number.
		/// </summary>
		/// <param name="name">The name of the value to write.</param>
		/// <param name="num">The value to write.</param>
		void write_value(const wchar_t* name, double num);
		/// <summary>
		/// Write a number.
		/// </summary>
		/// <param name="name">The name of the value to write.</param>
		/// <param name="num">The value to write.</param>
		void write_value(const wchar_t* name, int8_t num);
		/// <summary>
		/// Write a number.
		/// </summary>
		/// <param name="name">The name of the value to write.</param>
		/// <param name="num">The value to write.</param>
		void write_value(const wchar_t* name, int16_t num);
		/// <summary>
		/// Write a number.
		/// </summary>
		/// <param name="name">The name of the value to write.</param>
		/// <param name="num">The value to write.</param>
		void write_value(const wchar_t* name, int32_t num);
		/// <summary>
		/// Write a number.
		/// </summary>
		/// <param name="name">The name of the value to write.</param>
		/// <param name="num">The value to write.</param>
		void write_value(const wchar_t* name, int64_t num);
		/// <summary>
		/// Write a string.
		/// </summary>
		/// <param name="name">The name of the value to write.</param>
		/// <param name="string">The null-terminated string to write.</param>
		void write_value(const wchar_t* name, const wchar_t* string);
		/// <summary>
		/// Write a boolean.
		/// </summary>
		/// <param name="name">The name of the value to write.</param>
		/// <param name="val">The boolean to write.</param>
		void write_value(const wchar_t* name, bool val);
		/// <summary>
		/// Write a byte array.
		/// </summary>
		/// <param name="name">The name of the value to write.</param>
		/// <param name="data">The byte array to write.</param>
		/// <param name="sz">The size of the byte array, in bytes.</param>
		void write_value(const wchar_t* name, const byte* data, size_t sz);

		/// <summary>
		/// Read the start of an array.
		/// </summary>
		/// <param name="name">The name of the array to read.</param>
		/// <param name="sz">A required parameter holding the size of the array.</param>
		/// <returns>True if the array could be read.</returns>
		bool read_array_start(const wchar_t* name, size_t* sz);
		/// <summary>
		/// Read the start of an array.
		/// </summary>
		/// <param name="index">The index of the array to read.</param>
		/// <param name="sz">A required parameter holding the size of the array.</param>
		/// <returns>True if the array could be read.</returns>
		bool read_array_start(size_t index, size_t* sz);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="index">The index of the value to read.</param>
		/// <param name="num">A parameter which will hold the read value, or be default initialized if no value was read.</param>
		void read_array_value(size_t index, int8_t* num);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="index">The index of the value to read.</param>
		/// <param name="num">A parameter which will hold the read value, or be default initialized if no value was read.</param>
		void read_array_value(size_t index, int16_t* num);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="index">The index of the value to read.</param>
		/// <param name="num">A parameter which will hold the read value, or be default initialized if no value was read.</param>
		void read_array_value(size_t index, int32_t* num);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="index">The index of the value to read.</param>
		/// <param name="num">A parameter which will hold the read value, or be default initialized if no value was read.</param>
		void read_array_value(size_t index, int64_t* num);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="index">The index of the value to read.</param>
		/// <param name="string">A parameter which will hold the read value, or be default initialized if no value was read. This follows similar read semantics to the serializer.</param>
		void read_array_value(size_t index, wchar_t** string);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="index">The index of the value to read.</param>
		/// <param name="num">A parameter which will hold the read value, or be default initialized if no value was read.</param>
		void read_array_value(size_t index, double* num);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="index">The index of the value to read.</param>
		/// <param name="bit">A parameter which will hold the read value, or be default initialized if no value was read.</param>
		void read_array_value(size_t index, bool* bit);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="index">The index of the value to read.</param>
		/// <param name="data">A parameter which will hold the read value, or be default initialized if no value was read. This follows similar read semantics to the serializer.</param>
		/// <param name="sz">The size of the read data, in bytes.</param>
		void read_array_value(size_t index, byte** data, size_t* sz);
		/// <summary>
		/// Read the end of an array.
		/// </summary>
		void read_array_end();

		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="num">A parameter which will hold the read value, or be default initialized if no value was read.</param>
		void read_value(const wchar_t* name, double* num);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="num">A parameter which will hold the read value, or be default initialized if no value was read.</param>
		void read_value(const wchar_t* name, int8_t* num);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="num">A parameter which will hold the read value, or be default initialized if no value was read.</param>
		void read_value(const wchar_t* name, int16_t* num);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="num">A parameter which will hold the read value, or be default initialized if no value was read.</param>
		void read_value(const wchar_t* name, int32_t* num);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="num">A parameter which will hold the read value, or be default initialized if no value was read.</param>
		void read_value(const wchar_t* name, int64_t* num);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="string">A parameter which will hold the read value, or be default initialized if no value was read. This follows similar read semantics to the serializer.</param>
		void read_value(const wchar_t* name, wchar_t** string);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="val">A parameter which will hold the read value, or be default initialized if no value was read.</param>
		void read_value(const wchar_t* name, bool* val);
		/// <summary>
		/// Read a value.
		/// </summary>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="data">A parameter which will hold the read value, or be default initialized if no value was read. This follows similar read semantics to the serializer.</param>
		/// <param name="sz">The size of the read data, in bytes.</param>
		void read_value(const wchar_t* name, byte** data, size_t* sz);

		/// <summary>
		/// Read an object value into the specified location. If the value at this location exists, the object type will be used to construct it.
		/// </summary>
		/// <remarks>
		/// Any object being archived should be default constructible.
		/// This templated function will default-construct an object the first time
		/// before attempting to read from it.
		/// </remarks>
		/// <param name="name">The name of the value to read.</param>
		/// <param name="location">The location of the value being read.</param>
		template <typename T>
		void read_value(const wchar_t* name, T** location)
		{
			ReadValue(name, (object**)location, CtorFuncType(create_default_object<T>), false);
		}
		/// <summary>
		/// Read an object value into the specified location. If the value at this location exists, the object type will be used to construct it.
		/// </summary>
		/// <remarks>
		/// Any object being archived should be default constructible.
		/// This templated function will default-construct an object the first time
		/// before attempting to read from it.
		/// </remarks>
		/// <param name="index">The index of the value to read.</param>
		/// <param name="location">The location of the value being read.</param>
		template <typename T>
		void read_array_value(size_t index, T** location)
		{
			ReadValue(ArrayIndex(index), (object**)location, CtorFuncType(create_default_object<T>), false);
		}

		/// <summary>
		/// Represent a constructor functor.
		/// </summary>
		typedef std::function<object*(void)> CtorFuncType;

	private:

		const wchar_t* ArrayIndex(int64_t index);
		void TrackObject(object* obj);
		void ReleaseObjects();
		void WriteValue(const wchar_t* name, object* obj, bool root);
		bool ReadValue(const wchar_t* name, object** obj, CtorFuncType& ctorFunc, bool root);
		void PushObject(object* object);
		void PopObject();

		class ArrayState
		{
		public:
			int64_t MaxSize;
			ArrayState* _LastState;

			ArrayState();
			~ArrayState();

			static void* operator new(size_t sz);
			static void operator delete(void* ptr);
		};

		class ObjectState
		{
		public:
			object* Object;
			ObjectState* Last;

			ObjectState();
			~ObjectState();

			static void* operator new(size_t sz);
			static void operator delete(void* ptr);
		};

		m::serializer* _Serializer;
		ptrdiff_t _MaxId;
		object** _Fixup;
		ObjectState* _Objects;
		ArrayState* _Array;
		// Used for encoding array indices.
		wchar_t _Buf[20];
		ATOMIC_ALIGN CRITICAL_SECTION _ArchiverLock;
	};
}

/// <summary>
/// Represent the minimum amount by which 2 scalar values can differ.
/// </summary>
#define SCALAR_EPSILON 1.7e-8
/// <summary>
/// A boolean statement which can be used to evaluate if a given scalar is effectively zero.
/// </summary>
#define SCALAR_ZERO(X) (abs(X - SCALAR_EPSILON) < SCALAR_EPSILON)

namespace m
{

	class process;
	class process_manager;

	/// <summary>
	/// A message is used to communicate information from one process to another.
    /// It contains a message type and the location of an optional piece of data.
	/// </summary>
	/// <remarks>If a method or class uses specific message types their usage will typically be included in the remarks section of the documentation.</remarks>
	class message : public object
	{
	public:
		friend class process;
		friend class process_manager;

		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="sender">The message sender.</param>
		/// <param name="messageType">The message being sent.</param>
		/// <remarks>The message type is best expressed as a urn, e.g. us.sl.m.message</remarks>
		message(process* sender, const wchar_t* messageType);
		/// <summary>
		/// Constructor.
		/// </summary>
		/// <param name="sender">The message sender.</param>
		/// <param name="messageType">The message being sent.</param>
		/// <param name="data">The optional data to specify for the message.</param>
		message(process* sender, const wchar_t* messageType, object* data);
		virtual ~message();

		/// <summary>
		/// Specify the message sender.
		/// </summary>
		/// <returns>A weak reference to the sender of the message.</returns>
		weak_ref* sender() const;
		/// <summary>
		/// Specify the message data.
		/// </summary>
		/// <returns>The object data for the message.</returns>
		object* data() const;
		/// <summary>
		/// Specify the type of message being sent.
		/// </summary>
		/// <returns>The message type as a string.</returns>
		const wchar_t* type() const;
		/// <summary>
		/// Return if the type of this message equals the specified type.
		/// </summary>
		/// <param name="message">The type to evaluate.</param>
		/// <returns>True if the types are equal.</returns>
		bool type_equals(const wchar_t* message) const;

		static void* operator new(size_t sz);
		static void operator delete(void* ptr);
	private:

		message(const message&);
		message& operator=(const message&);

		message* _NextMessage;
		weak_ref* _Sender;
		object* _Data;
		wchar_t _Type[256];
		bool _Canceled;
	};

	typedef double scalar;

	/// <summary>
	/// Represent a timer state. You must hold a reference to this timer state for as long as your timer is running. The timer state holds information about a running game timer.
	/// </summary>
	class timer_state : public object
	{
	public:
		friend class process_manager;

		timer_state();
		virtual ~timer_state();

		/// <summary>
		/// Clear this timer state object.
		/// </summary>
		void clear();

		static void* operator new(size_t sz);
		static void operator delete(void* ptr);
	private:
		void CreateOrSet(process_manager* Pm, const scalar& delay, const scalar& interval, const bool& oneShot, process* Sender, const wchar_t* evt, object* data);

		friend VOID CALLBACK timer_stateCallback(
			_In_ PVOID   lpParameter,
			_In_ BOOLEAN TimerOrWaitFired
			);

		weak_ref* _PmWeak;
		HANDLE _Tmr;
		wchar_t* _Evt;
		weak_ref* _Sender;
		object* _Data;
	};

	/// <summary>
	/// Represent a game process.
	/// </summary>
	/// <remarks>
	/// <para>A process in our compositor represents a combination of background thread and message pump and it is intended
	/// to manage the lifetime of multiple related objects.This base process class is meant to be specialized.</para>
	/// 
	/// <para>A process receives multiple messages inside a message loop and handles them while the display is updating.
	/// The specialized "MONO_FRAME" message is called at the start of a frame when the process should begin updating
	/// animations.</para>
	/// </remarks>
	class process : public object
	{
	public:
		friend class process_manager;

		process();
		virtual ~process();

		/// <summary>
		/// Send a message of the given type from this process.
		/// </summary>
		/// <param name="message">The message to send.</param>
		void send(const wchar_t* message);
		/// <summary>
		/// Send a message of the given type from this process.
		/// </summary>
		/// <param name="message">The message to send.</param>
		/// <param name="data">The optional data to specify.</param>
		void send(const wchar_t* message, object* data);
		/// <summary>
		/// Send a message of the given type from this process.
		/// </summary>
		/// <param name="message">The message to send.</param>
		/// <param name="data">The optional data to specify.</param>
		/// <param name="cancelLast">True to cancel the last sent message.</param>
		void send(const wchar_t* message, object* data, bool cancelLast);

		/// <summary>
		/// Return if the process has been started.
		/// </summary>
		/// <returns>True if the process is started.</returns>
		bool started() const;
		/// <summary>
		/// Return if the process is running.
		/// </summary>
		/// <returns>True if the process is resumed.</returns>
		bool resumed() const;

		/// <summary>
		/// Set or update a timer, using the given timer state object as a tracking. Delay and interval are in seconds, and the last 2 parameters specify the event data to transmit.
		/// </summary>
		/// <param name="Ts">The timer state object to hold the data. If it is null, it will be created, otherwise it will be reused. You must release your reference to it when you are finished with it.</param>
		/// <param name="delay">The delay before the first tick in seconds.</param>
		/// <param name="interval">The interval between ticks.</param>
		/// <param name="evt">The event to send.</param>
		/// <param name="data">The optional data to specify for the event.</param>
		void set_periodic_timer(timer_state** Ts, const scalar& delay, const scalar& interval, const wchar_t* evt, object* data);
		/// <summary>
		/// Set or update a timer, using the given timer state object as a tracking. Delay and interval are in seconds, and the last 2 parameters specify the event data to transmit.
		/// </summary>
		/// <param name="Ts">The timer state object to hold the data. If it is null, it will be created, otherwise it will be reused. You must release your reference to it when you are finished with it.</param>
		/// <param name="delay">The delay before the first tick in seconds.</param>
		/// <param name="interval">The interval between ticks.</param>
		/// <param name="evt">The event to send.</param>
		void set_periodic_timer(timer_state** Ts, const scalar& delay, const scalar& interval, const wchar_t* evt);
		/// <summary>
		/// Set or update a timer, using the given timer state object as a tracking. A one shot timer ticks only once.
		/// </summary>
		/// <param name="Ts">The timer state object to hold the data. If it is null, it will be created, otherwise it will be reused. You must release your reference to it when you are finished with it.</param>
		/// <param name="delay">The delay before the first tick in seconds.</param>
		/// <param name="evt">The event to send.</param>
		/// <param name="data">The optional data to specify for the event.</param>
		void set_one_shot_timer(timer_state** Ts, const scalar& delay, const wchar_t* evt, object* data);
		/// <summary>
		/// Set or update a timer, using the given timer state object as a tracking. A one shot timer ticks only once.
		/// </summary>
		/// <param name="Ts">The timer state object to hold the data. If it is null, it will be created, otherwise it will be reused. You must release your reference to it when you are finished with it.</param>
		/// <param name="delay">The delay before the first tick in seconds.</param>
		/// <param name="evt">The event to send.</param>
		void set_one_shot_timer(timer_state** Ts, const scalar& delay, const wchar_t* evt);
		/// <summary>
		/// Clear a timer if it has been set.
		/// </summary>
		/// <param name="Ts">The location of the timer state object to clear.</param>
		void clear_timer(timer_state** Ts);

		/// <summary>
		/// Return if the process has a message to parse.
		/// </summary>
		/// <returns>True if there is a message to parse.</returns>
		bool has_message() const;

	protected:
		/// <summary>
		/// Wait for the next message, optionally putting the process
		/// in a blocking state if it's waiting on either another message or
		/// for the process to be resumed.
		/// </summary>
		/// <returns>True if a message was read.</returns>
		/// <remarks>After receiving a <code>us.sl.m.stop</code> event, the message handler will no longer work and the process should terminate immediately after handling it.</remarks>
		bool next_message();
		/// <summary>
		/// Message handler. A process must implement this and accept messages periodically to avoid leaking memory.
		/// </summary>
		virtual void process_entry() = 0;
		/// <summary>
		/// // Message handler. A process must implement this and accept the messages it wants to receive.
		/// </summary>
		/// <param name="m">The message to be received.</param>
		/// <returns>True if the message was handled.</returns>
		/// <remarks>The return type of this method is ignored by the process manager, but it is intended to be used in child classes.</remarks>
		virtual bool handle_message(message* m) = 0;

	private:
		process(const process&);
		process& operator=(const process&);

		friend static DWORD WINAPI ProcessThread(const LPVOID lParameter);

		void Enter();
		void Start(weak_ref* PmWeak, message* StartMessage);
		void Stop();

		message* _StartMsg;
		message* _CurMsg;
		weak_ref* _PmWeak;
		process* _LastProcess;
		process* _NextProcess;
		HANDLE _MessageThread;
		int _Read;
		bool _ForceStop;
		bool _Faulted;
	};

	/// <summary>The process manager manages the lifetime of multiple processes and acts as the delegate between
	/// the system and the process model of the compositor.</summary>
	/// <example>
	/// <para>The following example creates a process, sends a message to it, then stops the process manager.</para>
	/// <code>
	/// InternalProcess *p = new InternalProcess;
	/// process_manager* pm = new process_manager();
	/// pm->start();
	/// pm->add_process(p);
	/// p->send(0);
	/// pm->stop();
	/// </code>
	/// </example>
	class process_manager : public object
	{
	public:
		friend class process;
		friend class timer_state;

		process_manager();
		virtual ~process_manager();

		/// <summary>
		/// Send a message to the target process.
		/// </summary>
		/// <param name="sender">The optional message sender.</param>
		/// <param name="message">The message type to send.</param>
		void send(process* sender, const wchar_t* message);
		/// <summary>
		/// Send a message to the target process.
		/// </summary>
		/// <param name="sender">The optional message sender.</param>
		/// <param name="message">The message type to send.</param>
		/// <param name="data">The optional message data.</param>
		void send(process* sender, const wchar_t* message, object* data);
		/// <summary>
		/// Send a message to the target process.
		/// </summary>
		/// <param name="sender">The optional message sender.</param>
		/// <param name="message">The message type to send.</param>
		/// <param name="data">The optional message data.</param>
		/// <param name="cancelLast">True to cancel the last message beint sent.</param>
		void send(process* sender, const wchar_t* message, object* data, bool cancelLast);
		/// <summary>
		/// Start the process manager.
		/// </summary>
		/// <remarks>You must call this before adding any processes.</remarks>
		void start();
		/// <summary>
		/// Stop the process manager, removing all processes from it.
		/// </summary>
		/// <remarks>This will send a single <code>us.sl.m.stop</code> message which each process is expected to handle.</remarks>
		void stop();
		/// <summary>
		/// Pause the process manager, suspending message dispatch.
		/// </summary>
		void pause();
		/// <summary>
		/// Resume the process manager, allowing message dispatch to continue.
		/// </summary>
		void resume();
		/// <summary>
		/// Add a process to the process manager and automatically start it.
		/// </summary>
		/// <param name="process">The process to add.</param> 
		/// <remarks>This will send a single <code>us.sl.m.start</code> message with the process to be added as data.</remarks>
		void add_process(process* process);
		/// <summary>
		/// Remove a process from the process manager.
		/// </summary>
		/// <param name="process">The process to remove.</param>
		/// <remarks>This will send a single <code>us.sl.m.stop</code> message with the process to be removed as data, which that process is expected to handle.</remarks>
		void remove_process(process* process);
		/// <summary>
		/// Flush any outstanding messages in the process message buffer.
		/// </summary>
		/// <remarks>This is intended for debugging only.</remarks>
		void flush();

		/// <summary>
		/// Return if the process manager has been started. 
		/// </summary>
		/// <returns>True if the process manager is started.</returns>
		const bool& started() const;
		/// <summary>
		/// Return if the process manager is running.
		/// </summary>
		/// <returns>True if the process manager is not paused.</returns>
		const bool& resumed() const;

	private:
		void Send(message* msg, bool cancelLast);
		bool GetNext(message** msg);
		bool HasMessageAbove(const message* msg) const;
		void Remove(process* thisProc);
		message* FindFirstMessage();

		// process timer management.
		void ChangeTimer(timer_state** Ts, const scalar& delay, const scalar& interval, const bool& oneShot, process* Sender, const wchar_t* evt, object* data);
		void ClearTimer(timer_state** Ts);

		mutable CRITICAL_SECTION _ProcessLock;
		mutable SRWLOCK _MessageLock;
		CONDITION_VARIABLE _MessageEvent;
		message* _LastMessage;
		process* _FirstProcess;
		size_t _NumProcesses;
		int _Sent;
		// Necessary for timer queue functionality. 
		HANDLE _TimerQ;
		size_t _Stopped;
		bool _Started;
		bool _Running;
	};
}

namespace m
{
	namespace io
	{
		/// <summary>
		/// Represent the type of file transaction to perform.
		/// </summary>
		/// <remarks>This is intended for internal use only.</remarks>
		enum FileOperation
		{
			ReadFile,
			WriteFile
		};

		/// <summary>
		/// Represent a chunk of contiguous file data.
		/// </summary>
		class _file_data
		{
		public:
			friend class file_buffer;

			_file_data();
			~_file_data();

			/// <summary>
			///  Initialize the file data object.
			/// </summary>
			/// <param name="src">The source data for initialization.</param>
			/// <param name="length">The length of the source data.</param>
			void initialize(const char* src, const size_t& length);
			/// <summary>
			/// Split count bytes to the left, placing the bytes after that into the specified FileData object.
			/// </summary>
			/// <param name="countLeft">The size in bytes of the space to the left.</param>
			/// <param name="RightBits">The object containing the remaining data.</param>
			/// <remarks>If countLeft is too large, the data to the left will be truncated.</remarks>
			void split(const size_t& countLeft, _file_data* RightBits);

			static void* operator new(size_t sz);
			static void operator delete(void* ptr);

			/// <summary>
			/// The buffer being held.
			/// </summary>
			char* Buffer;
			/// <summary>
			/// The buffer length.
			/// </summary>
			size_t Length;

		private:
			void Clear();

			_file_data* _Next;
			_file_data* _Prev;
		};

		/// <summary>
		/// Represent the state of a file transaction in progress.
		/// A file can either be read to or written from. In either
		/// case, a blob of data representing a read or write
		/// transaction is stored here.
		/// </summary>
		class file_buffer : public object
		{
		public:
			friend class file_streamer;

			file_buffer();
			~file_buffer();

			/// <summary>
			/// Return the size of file buffer.
			/// </summary>
			/// <returns>The size, in bytes, of the buffer.</returns>
			size_t size() const;
			/// <summary>
			/// Set the size of the file buffer.
			/// </summary>
			/// <param name="Size">The size, in bytes, of the buffer.</param>
			void set_size(const size_t& Size);
			/// <summary>
			/// Return the current file offset.
			/// </summary>
			/// <returns>The offset into the file, in bytes.</returns>
			const ptrdiff_t& offset() const;
			/// <summary>
			/// Set the current offset into the file.
			/// </summary>
			/// <param name="off">The offset, in bytes, which should be forward to advance the file, else negative.</param>
			void set_offset(const ptrdiff_t& off);
			/// <summary>
			/// Read from the file, copying the output to the specified buffer and advancing the offset by len.
			/// Returns the number of bytes read or 0 if no more bytes could be read.
			/// </summary>
			/// <param name="buffer">The buffer holding the data to be read.</param>
			/// <param name="len">The length of the buffer.</param>
			/// <returns>The size of the data which was read in the buffer, which will not exceed the buffer length.</returns>
			/// <remarks>Less data may be read into the buffer than its size.</remarks>
			size_t read(char* buffer, const size_t& len);
			/// <summary>
			/// Write to the file, copying the output from the specified buffer and advancing the offset by len.
			/// </summary>
			/// <param name="buffer">The data to be written.</param>
			/// <param name="len">The size of the buffer, in bytes.</param>
			void write(const char* buffer, const size_t& len);
			/// <summary>
			/// Clear the file buffer.
			/// </summary>
			void clear();

			/// <summary>
			/// Generate an exception if the transaction failed.
			/// </summary>
			void ThrowIfHr() const;

			static void* operator new(size_t sz);
			static void operator delete(void* ptr);

		private:
			void Erase(size_t size, size_t len);

			ATOMIC_ALIGN SLIST_ENTRY _ListEntry;
			// Either we could keep the file name here or the handle but the handle
			// structures might actually be different so just keep the file name.
			wchar_t* _FileName;
			FileOperation _Operation;
			_file_data* _StartOfData;
			ptrdiff_t _Offset;
			ptrdiff_t _BlockStart;
			_file_data* _CurBlock;
			HRESULT _Hr;
		};
		/// <summary>
		/// Represent a binary serializer for storing objects in a binary format.
		/// </summary>
		/// <remarks>This class follows the semantics of the base serializer class.</remarks>
		class binary_serializer : public serializer
		{
		public:
			binary_serializer();
			virtual ~binary_serializer();

			virtual void write_object_start(const wchar_t* name);
			virtual void write_object_end();
			virtual void write_value(const wchar_t* name, const wchar_t* string);
			virtual void write_value(const wchar_t* name, double num);
			virtual void write_value(const wchar_t* name, int8_t num);
			virtual void write_value(const wchar_t* name, int16_t num);
			virtual void write_value(const wchar_t* name, int32_t num);
			virtual void write_value(const wchar_t* name, int64_t num);
			virtual void write_value(const wchar_t* name, bool bit);
			virtual void write_value(const wchar_t* name, const byte* data, size_t sz);

			virtual bool read_object_start(const wchar_t* name, size_t* countObjects);
			virtual void read_object_end();
			virtual void read_value(const wchar_t* name, wchar_t** string);
			virtual void read_value(const wchar_t* name, double* num);
			virtual void read_value(const wchar_t* name, int8_t* num);
			virtual void read_value(const wchar_t* name, int16_t* num);
			virtual void read_value(const wchar_t* name, int32_t* num);
			virtual void read_value(const wchar_t* name, int64_t* num);
			virtual void read_value(const wchar_t* name, bool* bit);
			virtual void read_value(const wchar_t* name, byte** data, size_t* sz);

			/// <summary>
			/// Attempts to load the given buffer into the serializer.
			/// </summary>
			/// <param name="buffer">The buffer to load data from.</param>
			/// <remarks>If reading the document, must call load() before passing serializer to an archiver.</remarks>
			void load(file_buffer* buffer);
			/// <summary>
			/// Attempt to save the given buffer from the serializer.
			/// </summary>
			/// <param name="buffer">The buffer to save data into.</param>
			/// <remarks>If writing the document, must call save() to persist the changes to a file.</remarks>
			void save(file_buffer* buffer);

		private:
			enum BinaryType
			{
				TypeUnknown,
				TypeObject,
				TypeString,
				TypeDouble,
				TypeInt8,
				TypeInt16,
				TypeInt32,
				TypeInt64,
				TypeBool
			};

			/*
				Serialized binary data assumes this form. Child, Sibling
				and parent pointers are specified for objects which support it.
			*/

			class BinaryRecord
			{
			public:
				/*
					These values are stored for each record.
				*/

				int64_t Id;
				binary_serializer::BinaryType Type;
				int64_t CchName;
				wchar_t* Name;
				int64_t CountData;
				byte* StartOfData;

				/*
					These persist the binary record to the given buffer.
				*/

				BinaryRecord();
				~BinaryRecord();

				static void* operator new(size_t sz);
				static void operator delete(void* ptr);

				/*
					These methods values are provided for object type data
					and no-op for everything else.
				*/

				int64_t Parent;
			};


			static uint16_t CalculateChecksum(file_buffer* buffer);
			BinaryRecord* InsertValue(const wchar_t* name, const byte* value, int64_t Sz, BinaryType type);
			BinaryRecord* ValueFor(const wchar_t* Name, const BinaryType& ExpectedType);
			void ClearRecords();

			BinaryRecord** _Records;
			size_t _LastRecord;
			size_t _CountRecords;
			BinaryRecord* _CurRecord;
		};

		/// <summary>
		/// Represent a process which performs on demand file streaming
		/// operations. The file streamer reads or writes one file at a time
		/// in succession, informing the caller when the file is loaded.
		/// Files are assumed to be blobs of binary data which stay resident
		/// until released.
		/// </summary>
		/// <remarks>
		/// <para>These operations support reading out of cabinet archives as well as loose files on disk.
		/// An example of a cabinet path: foo.cab\bar\file.txt</para>
		/// <para>Would read bar\file.txt out of foo.cab in the current working directory.
		/// These operations do not support reading out of nested cabinets.</para>
		/// </remarks>
		class file_streamer : public process
		{
		public:
			file_streamer();

			/// <summary>
			/// Read a file into the given FileState object. The buffer object will contain a copy of the buffered data to be read.
			/// While this is happening, the called should treat the file_buffer object as in use, and should not attempt to modify it in any way.
			/// </summary>
			/// <param name="Fs">The file to read into.</param>
			/// <param name="FileName">The name of the file being read.</param>
			/// <remarks>This will generate a <code>us.sl.m.readStart</code> message pointing to the buffer to read, and the streamer will generate a corresponding <code>us.sl.m.readComplete</code> message on completion of the read.</remarks>
			void read_file(file_buffer* Fs, const wchar_t* FileName);
			/// <summary>
			/// Write a buffer to the given file. The buffer object will contain a copy of the buffered data to be written. 
            /// While this is happening, the caller should treat the file_buffer object as in use, and should not attempt to modify it in any way.
			/// </summary>
			/// <param name="Fs">The file to write from.</param>
			/// <param name="FileName">The name of the file being written.</param> 
			/// <remarks>This will generate a <code>us.sl.m.writeStart</code> message pointing to the buffer to read, and the streamer will generate a corresponding <code>us.sl.m.writeComplete</code> message on completion of the read.</remarks>
			void write_file(file_buffer* Fs, const wchar_t* FileName);

		protected:
			virtual void process_entry();
			virtual bool handle_message(message* m);

		private:
			void HandleFile(file_buffer* Fs);
			void ReadCabinet(file_buffer* State, LPCWSTR CabPath, LPCWSTR FileName);
			void ReadLoose(file_buffer* State, LPCWSTR FilePath);
			void WriteCabinet(file_buffer* State, LPCWSTR CabPath, LPCWSTR FileName);
			void WriteLoose(file_buffer* State, LPCWSTR FilePath);
		};
	}
}

#include "7za.h"

namespace m
{
	namespace alloc
	{
		/// <summary>
		/// Represent a process which cleans the pool at a specified interval,
		/// normally 1s. Pooled memory becomes overloaded, and the pool
		/// cleaner keeps a running average of each pools usage and determine
		/// how much extra memory can be freed. To do this, it has access
		/// to initialize code which normally isn't available to processes.
		/// </summary>
		/// <remarks>This process creates a timer which will intermittently fire <code>us.sl.m.poolClean</code> messages to manage native heap space.</remarks>
		class pool_cleaner : public process
		{
		public:
			pool_cleaner();
			~pool_cleaner();

			/// <summary>
			/// Hold the calculated total used pool size, based on the last clean pass.
			/// </summary>
			volatile ATOMIC_ALIGN size_t UsedPoolSize;

		protected:
			virtual void process_entry();
			virtual bool handle_message(message* m);

		private:
			timer_state* _PoolTimer;
			size_t _Cleaned;
			int _Cycle;
		};

	}
}

#define ROOT_NAME L"."

namespace m
{
	/// <summary>
	/// Utilities for representation of text data. Provides utility methods for handling large
	/// amounts of text in memory, as well as for handling JSON documents and
	/// serializing object models as text file using JSON.
	/// </summary>
	namespace text
	{
		/// <summary>
		/// Represent different text encodings for the buffer below.
		/// </summary>
		/// <remarks>The invalid encoding should not be passed to any method.</remarks>
		enum TextEncoding
		{
			TextEncodingAscii,
			TextEncodingUtf8,
			TextEncodingUtf16,
			TextEncodingInvalid,
		};

		/// <summary>
		/// Represent a wide formatted text buffer, which can read or write to a file based on a given encoding.
		/// </summary>
		class text_buffer : public object
		{
		public:
			typedef io::file_buffer BaseType;

			text_buffer();
			~text_buffer();

			/// <summary>
			/// Read the text from the given file state
			/// and return the text encoding of the document.
			/// </summary>
			/// <param name="state">The file buffer into which the text is being read.</param>
			/// <returns>The detected encoding of the text file.</returns>
			TextEncoding load(io::file_buffer* state);
			/// <summary>
			/// Save the text in the given encoding.
			/// </summary>
			/// <param name="state">The file buffer from which the text is being written.</param>
			/// <param name="encoding">The encoding of the text file.</param>
			void save(io::file_buffer* state, TextEncoding encoding);


			/// <summary>
			/// Return the size of the text buffer.
			/// </summary>
			/// <returns>The size in characters of the text buffer.</returns>
			size_t size() const;
			/// <summary>
			/// Set the size of the text buffer.
			/// </summary>
			/// <param name="Size">The size in characters of the text buffer.</param>
			void set_size(const size_t& Size);
			/// <summary>
			/// Return the current file offset.
			/// </summary>
			/// <returns>The offset in characters of the text buffer.</returns>
			ptrdiff_t offset() const;
			/// <summary>
			/// Set the current offset into the file.
			/// </summary>
			/// <param name="off">The offset in characters of the text buffer.</param>
			void set_offset(const ptrdiff_t& off);

			/// <summary>
			/// Return the next character from the reader or null if no further character
			/// could be read.
			/// </summary>
			/// <returns>A single character or null.</returns>
			wchar_t read();
			/// <summary>
			/// Return up to the next N characters from the reader or null of no further character could be read.
			/// </summary>
			/// <param name="Buffer">The text buffer to read into.</param>
			/// <param name="BufferSize">The size of the buffer in characters.</param>
			/// <returns>The number of characters read into the buffer, excluding the terminating null character.</returns>
			/// <remarks>Don't forget to allocate enough space for the terminating null character in your buffer.</remarks>
			size_t read(wchar_t* Buffer, const size_t& BufferSize);
			/// <summary>
			/// Write a character to the buffer.
			/// </summary>
			/// <param name="ch">The character to write.</param>
			void write(wchar_t ch);
			/// <summary>
			/// Write up to N characters to a buffer.
			/// </summary>
			/// <param name="Buffer">The buffer containing the text to write.</param>
			void write(const wchar_t* Buffer);

		private:
			TextEncoding Encoding(io::file_buffer* state) const;

			io::file_buffer* _TextBuffer;
		};

		/// <summary>
		/// Represent types of JSON text.
		/// </summary>
		/// <see href="http://www.json.org">The JSON foundation.</see>
		enum JsonNodeType
		{
			JsonObject,
			JsonArray,
			JsonString,
			JsonNumber,
			JsonBool,
			JsonNil
		};

		/// <summary>
		/// Represent a node in the JSON hierarchy.
		/// </summary>
		class json_node : public object
		{
		public:
			friend class json_document;

			json_node();
			~json_node();

			/// <summary>
			/// Remove this node and all descendants from the hierarchy.
			/// </summary>
			/// <returns>Returns if the note could be removed.</returns>
			bool remove();

			/// <summary>
			/// Return the node's name.
			/// </summary>
			/// <returns>A null terminated string.</returns>
			const wchar_t* name() const;
			/// <summary>
			/// Set the node's name.
			/// </summary>
			/// <param name="Name">A null terminated string containing the name.</param>
			void set_name(const wchar_t* Name);

			/// <summary>
			/// Return the node's type.
			/// </summary>
			/// <returns>The type of the node.</returns>
			JsonNodeType type() const;

			/// <summary>
			/// Return the node child.
			/// </summary>
			/// <returns>A node.</returns>
			/// <remarks>This is always the first node child.</remarks>
			json_node* child() const;
			/// <summary>
			/// Return the node's next sibling.
			/// </summary>
			/// <returns>A node.</returns>
			json_node* sibling() const;

			/// <summary>
			/// Insert a sibling after this node.
			/// </summary>
			/// <param name="sibling">The node to insert.</param>
			/// <returns>True if the value could be inserted.</returns>
			bool insert_after(json_node* sibling);
			/// <summary>
			/// Insert a child under this node.
			/// </summary>
			/// <param name="child">The node to insert.</param>
			/// <returns>True if the value could be inserted.</returns>
			bool insert_child(json_node* child);

			/// <summary>
			/// Return if the node is a nil value.
			/// </summary>
			/// <returns>A boolean.</returns>
			bool is_nil() const;
			/// <summary>
			/// Return if the node is an array value.
			/// </summary>
			/// <returns>A boolean.</returns>
			bool is_array() const;
			/// <summary>
			///  Return if the node is an object value.
			/// </summary>
			/// <returns>A boolean.</returns>
			bool is_object() const;
			/// <summary>
			/// Return the boolean representation of the node.
			/// </summary>
			/// <returns>A boolean.</returns>
			bool as_bool() const;
			/// <summary>
			/// Return the numeric representation of the node.
			/// </summary>
			/// <returns>A number.</returns>
			double as_number() const;
			/// <summary>
			/// Return the string representation of the node.
			/// </summary>
			/// <returns>A string.</returns>
			const wchar_t* as_string() const;

			/// <summary>
			/// Return the count of children or in the case of an array the size of the array.
			/// </summary>
			/// <returns>The number of children of this node.</returns>
			size_t count() const;

			/// <summary>
			/// Set the node to nil.
			/// </summary>
			void set_nil();
			/// <summary>
			/// Set the node to an array type.
			/// </summary>
			void set_array();
			/// <summary>
			/// Set the node to an object type.
			/// </summary>
			void set_object();
			/// <summary>
			/// Set the node value.
			/// </summary>
			/// <param name="Value">The string value to set.</param>
			void set_value(const wchar_t* Value);
			/// <summary>
			/// Set the node value.
			/// </summary>
			/// <param name="Value">The boolean value to set.</param>
			void set_value(bool Value);
			/// <summary>
			/// Set the node value.
			/// </summary>
			/// <param name="Value">The number value to set.</param>
			void set_value(double Value);

			static void* operator new(size_t sz);
			static void operator delete(void* ptr);

		private:
			void ClearName();
			void ClearValue();

			union NodeStorage
			{
				double NumberValue;
				wchar_t* StringValue;
				bool BoolValue;
			};

			wchar_t* _Name;
			JsonNodeType _Type;
			NodeStorage _Data;
			weak_ref* _Parent;
			json_node* _Child;
			json_node* _Sibling;
		};

		/// <summary>
		/// Represent a format exception for JSON errors, containing extra information.
		/// </summary>
		class json_format_exception : public bad_result_exception
		{
		public:
			typedef bad_result_exception BaseType;

			/// <summary>
			/// The line of the error.
			/// </summary>
			int Line;
			/// <summary>
			/// The column fo the error.
			/// </summary>
			int Col;

			json_format_exception();
			json_format_exception(json_format_exception& other);
			json_format_exception(const int& line, const int& col, const char* const& message);

			json_format_exception& operator=(const json_format_exception& other);
		};

		/// <summary>
		/// Represent a searchable archivable JSON document model.
		/// </summary>
		class json_document : public object
		{
		public:
			json_document();
			~json_document();

			/// <summary>
			/// Load the document.
			/// </summary>
			/// <param name="Reader">The buffer containing the document text.</param>
			void load_document(text_buffer* Reader);
			/// <summary>
			/// Save the document.
			/// </summary>
			/// <param name="Writer">The buffer containing the document text.</param>
			void save_document(text_buffer* Writer);

			/// <summary>
			/// Return the root of the document.
			/// </summary>
			/// <returns>The root node, if any.</returns>
			const json_node* root() const;
			/// <summary>
			/// Return the root of the document.
			/// </summary>
			/// <returns>The root, if any.</returns>
			json_node* root();
			/// <summary>
			/// Set the root of the document.
			/// </summary>
			/// <param name="Root">The root.</param>
			void set_root(json_node* Root);

		private:
			void WriteValue(json_node* cur);
			void WriteObject(json_node* cur);
			void WriteArray(json_node* cur);
			void WriteNumber(json_node* cur);
			void WriteBool(json_node* cur);
			void WriteString(json_node* cur);
			void WriteNil(json_node* cur);
			void WriteWhitespace();

			json_node* ReadValue(LPCWSTR endToken);
			wchar_t ReadToken();
			json_node* ReadObject();
			json_node* ReadArray();
			json_node* ReadString();

			void ResetParser(text_buffer* Buffer);
			wchar_t PopChar();

			json_node* _Root;
			text_buffer* _Buffer;
			int _Line;
			int _Col;
			char _Indent;
		};

		/// <summary>
		/// Represent a text-based object serializer.
		/// </summary>
		/// <remarks>This class follows the semantics of the base serializer class.</remarks>
		class text_serializer : public serializer
		{
		public:
			text_serializer();
			virtual ~text_serializer();

			virtual void write_object_start(const wchar_t* name);
			virtual void write_object_end();
			virtual void write_value(const wchar_t* name, const wchar_t* string);
			virtual void write_value(const wchar_t* name, double num);
			virtual void write_value(const wchar_t* name, int8_t num);
			virtual void write_value(const wchar_t* name, int16_t num);
			virtual void write_value(const wchar_t* name, int32_t num);
			virtual void write_value(const wchar_t* name, int64_t num);
			virtual void write_value(const wchar_t* name, bool bit);
			virtual void write_value(const wchar_t* name, const byte* data, size_t sz);

			virtual bool read_object_start(const wchar_t* name, size_t* countChildren);
			virtual void read_object_end();
			virtual void read_value(const wchar_t* name, wchar_t** string);
			virtual void read_value(const wchar_t* name, double* num);
			virtual void read_value(const wchar_t* name, int8_t* num);
			virtual void read_value(const wchar_t* name, int16_t* num);
			virtual void read_value(const wchar_t* name, int32_t* num);
			virtual void read_value(const wchar_t* name, int64_t* num);
			virtual void read_value(const wchar_t* name, bool* bit);
			virtual void read_value(const wchar_t* name, byte** data, size_t* sz);

			/// <summary>
			/// Clear the text from the serializer.
			/// </summary>
			void clear();
			/// <summary>
			/// Load the given buffer into the serializer.
			/// </summary>
			/// <param name="buffer">The buffer containing the serialized data.</param>
			/// <remarks>If reading the document, must call load() before passing serializer to an archiver</remarks>
			void load(text_buffer* buffer);
			/// <summary>
			/// Save the serialized data into the buffer.
			/// </summary>
			/// <param name="buffer">The buffer containing the serialized data.</param>
			/// <remarks>If writing the document, must call save() to persist the changes to a file</remarks>
			void save(text_buffer* buffer);

		private:
			class ObjectState
			{
			public:
				json_node* Object;
				ObjectState* Last;

				ObjectState();
				~ObjectState();

				static void* operator new(size_t sz);
				static void operator delete(void* ptr);
			};

			json_node* ValueFor(const wchar_t* name);
			void InsertValue(json_node* node);
			void PushObject(json_node* node);
			void PopObject();
			json_node* CurObject();

			ObjectState* _Objects;
			json_document* _Document;
			json_node* _Last;
			wchar_t _Buf[DBL_MAX_10_EXP + 1];
		};
	} // namespace text
} // namespace m

#define PACKAGE_METADATA L"PackageMetadata.json"

namespace m
{
	/// <summary>
	/// Represent a modifiable package, which can be updated using the package manager process.
	/// </summary>
	class package : public object
	{
	public:
		friend class package_manager;

		package();
		~package();

		/// <summary>
		/// Return the package metadata.
		/// </summary>
		/// <returns>An archivable metadata object.</returns>
		object* metadata();
		/// <summary>
		/// Set the package metadata.
		/// </summary>
		/// <param name="packageMetadata">An archivable metadata objec.t</param>
		void set_metadata(object* packageMetadata);

		/// <summary>
		/// Add a file to the package.
		/// </summary>
		/// <param name="archivePath">The archival path.</param>
		/// <param name="diskPath">The path of the file on disk.</param>
		void add_file(const wchar_t* archivePath, const wchar_t* diskPath);
		/// <summary>
		/// Add a file to the package.
		/// </summary>
		/// <param name="archivePath">The archival path.</param>
		/// <param name="buffer">A buffer containing the file.</param>
		void add_file(const wchar_t* archivePath, io::file_buffer* buffer);

		/// <summary>
		/// Return the result of attempting to archive the package.
		/// </summary>
		/// <returns>The archival result.</returns>
		/// <remarks>You should inspect this value after making any call to package_manager::save</remarks>
		int get_result() const;

	private:

		class FileList
		{
		public:
			FileList();
			~FileList();

			wchar_t* Root;
			wchar_t* FilePath;
			io::file_buffer* Buffer;
			FileList* Next;
		};

		wchar_t* _PackageName;
		object* _Metadata;
		FileList* _FirstFile;
		wchar_t* _AssemblyDir;
		int _Result;
		bool _Overwrite;
	};

	/// <summary>
	/// Represent a process for asynchronously modifying packages on disk.
	/// </summary>
	class package_manager : public process
	{
	public:
		package_manager();
		~package_manager();

		/// <summary>
		/// Save a package to disk.
		/// </summary>
		/// <param name="packageName">The name of the package to save.</param>
		/// <param name="package">The package to save.</param>
		/// <param name="overwritable">True if the package should be overwritten if it already exists.</param>
		/// <remarks>If the package already exists and overwritable is false, the package will not be written.</remarks>
		/// <remarks>This will generate a <code>us.sl.m.savePackageStart</code> message pointing to the package to write, and the manager will generate a corresponding <code>us.sl.m.savePackageComplete</code> message on completion of the operation.</remarks>
		void save(const wchar_t* packageName, package* package, bool overwritable);

	protected:
		virtual void process_entry();
		virtual bool handle_message(message* message);

	private:
		void WritePackage(package* package);
		bool WriteFile(package* package, package::FileList* fileData);

		text::text_serializer* _Serializer;
		text::text_buffer* _Buffer;
		archiver* _Archiver;
	};
}

#endif // _M_H_